export enum Receive {
  CONNECT = 'CONNECT',
  MESSAGE = 'MESSAGE',
  LOGIN_SUCCESS = 'LOGIN_SUCCESS',
  UPDATE = 'UPDATE',
  KEEPALIVE = 'KEEPALIVE',
  CONNECTED = 'CONNECTED'
}

export enum Send {
  MESSAGE = 'MESSAGE',
  LOGIN = 'LOGIN',
  KEEPALIVE = 'KEEPALIVE'
}

type DataType<T extends Send | Receive> = T extends Send ? MessageSendData[Send] : MessageReceiveData[Receive];

export interface MessageBody<T extends Send | Receive> {
  action: T;
  data?: DataType<T>;
}

export interface MessageReceiveData {
  [Receive.CONNECT]: never;
  [Receive.MESSAGE]: ChatMessage;
  [Receive.LOGIN_SUCCESS]: ChatMessage;
  [Receive.UPDATE]: Update;
  [Receive.KEEPALIVE]: ChatMessage;
  [Receive.CONNECTED]: never;
}

export interface MessageSendData {
  [Send.MESSAGE]: ChatMessage;
  [Send.LOGIN]: ChatMessage;
  [Send.KEEPALIVE]: never;
}

export type Update = string;

export interface ChatMessage {
  [key: string]: any;
}
